package cn.agiledata.bank.common.util;
/*
 * by cyril on 2008-04-14
 * email: zjjsgwm@163.com
 */
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * 使用3DES加密, 并使用HEX的字符串形式传输
 */
public class DES {
	private static final String DES = "DESede";

	/**
	 * 生成3DES密钥
	 * 
	 * @param b
	 *            密钥串
	 * @return
	 * @throws Exception
	 */
	public static SecretKey gen3DESKey(byte[] b) throws Exception {
		SecretKey k = new SecretKeySpec(b, DES);
		return k;
	}

	/**
	 * 3DES加密
	 * 
	 * @param key
	 *            密钥
	 * @param b
	 *            明文(二进制型)
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(SecretKey key, byte[] b) throws Exception {
		Cipher cipher = Cipher.getInstance(DES);
		cipher.init(Cipher.ENCRYPT_MODE, key);
		return cipher.doFinal(b);
	}

	/**
	 * 3DES解密
	 * 
	 * @param key
	 *            密钥
	 * @param b
	 *            密文
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(SecretKey key, byte[] b) throws Exception {
		Cipher cipher = Cipher.getInstance(DES);
		cipher.init(Cipher.DECRYPT_MODE, key);
		return cipher.doFinal(b);
	}

	/**
	 * 二进制转十六进制
	 * 
	 * @param b
	 *            二进制
	 * @return
	 */
	public static String byte2Hex(byte[] b) {
		char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		char[] s = new char[b.length * 2];
		for (int i = 0; i < b.length; i++) {
			s[2 * i] = hex[(b[i] & 0xf0) >> 4];
			s[2 * i + 1] = hex[b[i] & 0xf];
		}
		return new String(s);
	}

	/**
	 * 十六进制转二进制
	 * 
	 * @param s
	 *            十六进制(String型)
	 * @return
	 */
	public static byte[] hex2Byte(String s) {
		int len = s.length();
		if (len % 2 == 1)
			return null;
		byte[] b = new byte[len / 2];
		for (int i = 0; i < len / 2; i++) {
			int j = 0;
			Integer t;
			char ch1 = s.charAt(i * 2);
			char ch2 = s.charAt(i * 2 + 1);
			if ((ch1 >= 'A') && (ch1 <= 'F'))
				j = (ch1 - 'A' + 10) * 16;
			if ((ch1 >= '0') && (ch1 <= '9'))
				j = (ch1 - '0') * 16;
			if ((ch2 >= 'A') && (ch2 <= 'F'))
				j = j + (ch2 - 'A' + 10);
			if ((ch2 >= '0') && (ch2 <= '9'))
				j = j + (ch2 - '0');
			if ((((ch2 >= 'A') && (ch2 <= 'F')) || ((ch2 >= '0') && (ch2 <= '9'))) != true)
				return null;
			if ((((ch1 >= 'A') && (ch1 <= 'F')) || ((ch1 >= '0') && (ch1 <= '9'))) != true)
				return null;
			t = new Integer(j);
			b[i] = t.byteValue();
		}
		return b;
	}

	/**
	 * 测试程序
	 * 
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		String text = new String("merchid=989898989898989&cardNo_transin=9000019067996317334&cardNo_transout=9444448964601981739&cardpin=111111&transferamt=80000.99&merchssn=123456&merchtime=200804101010&memo=转帐描述");
		byte key[] = "12340E78123459F1A23450E8".getBytes();// 3DES key

		try {
			// 生成DES密钥
			SecretKey skey = gen3DESKey(key);
			System.out.println("gen3DESKey OK.");

			byte[] e, d;
			// 加密
			e = encrypt(skey, text.getBytes());
			System.out.println("encrypt OK.");
			// 解密
			d = decrypt(skey, e);
			System.out.println("解密=[" + new String(d) + "]");

			// 转成HEX
			String hex = byte2Hex(e);
			System.out.println("HEX=[" + hex + "]");

			String tempHex = "C7591463E4B3E5EBB5482D271A00760F0272D55A5BEFEA7F";
			byte[] temp = hex2Byte(tempHex);
			String tempStr = new String(decrypt(skey, temp));
			System.out.println("HEX 解密=[" + tempStr + "]");

			System.out.println("decrypt OK.");
		} catch (Exception e) {
			System.out.println("Please check the key.");
			e.printStackTrace();
		}
	}
}
